package com.javabi.codegenerator.java.object.executable;

import static com.javabi.codeobject.java.type.classtype.ClassType.CLASS;
import static com.javabi.codeobject.java.type.classtype.ClassType.INTERFACE;

import java.util.ArrayList;
import java.util.List;

import com.javabi.codegenerator.java.model.JavaModel;
import com.javabi.codegenerator.java.model.bean.JavaModelBean;
import com.javabi.codegenerator.java.model.executable.JavaModelExecutableSerializer;
import com.javabi.codegenerator.java.object.JavaObjectGenerator;
import com.javabi.codegenerator.java.object.executable.method.ReadObjectMethod;
import com.javabi.codegenerator.java.object.executable.method.WriteObjectMethod;
import com.javabi.codegenerator.java.object.model.IJavaContext;
import com.javabi.codegenerator.java.setup.ISetup;
import com.javabi.codeobject.java.object.JavaObject;
import com.javabi.codeobject.java.type.IJavaType;
import com.javabi.codeobject.java.type.JavaTypeGenericSymbol;
import com.javabi.codetype.bean.executable.IExecutableBean;
import com.javabi.codetype.serializer.data.IDataSerializer;

public class JavaExecutableSerializerGenerator extends JavaObjectGenerator {

	private final JavaModelExecutableSerializer serializer;
	private IJavaType interfaceType;
	private IJavaType type;
	private IJavaType beanType;

	public JavaExecutableSerializerGenerator(ISetup setup, IJavaContext context, JavaModel model, JavaModelExecutableSerializer serializer) {
		super(setup, context, model, serializer.get());
		this.serializer = serializer;
	}

	public JavaModelExecutableSerializer getSerializer() {
		return serializer;
	}

	@Override
	public void registerPrimaryTypes() {
		interfaceType = registerJavaType("I" + getSerializer().getName(), INTERFACE);
		type = registerJavaType(getSerializer().getName(), CLASS);
		beanType = resolve(IExecutableBean.class, new JavaTypeGenericSymbol("?"));
	}

	@Override
	public void verifyReferencedTypes() {
	}

	@Override
	public void generate() {
		List<JavaModelBean> beanList = getBeanList();

		JavaObject objectInterface = new JavaObject(interfaceType);
		objectInterface.addExtends(resolve(IDataSerializer.class, beanType));

		JavaObject object = new JavaObject(type);
		object.addExtends(interfaceType);

		object.addBlock(new ReadObjectMethod(beanType, beanList));
		object.addBlock(new WriteObjectMethod(beanType, beanList));

		// Done!
		write(objectInterface);
		write(object);
	}

	private List<JavaModelBean> getBeanList() {
		List<JavaModelBean> list = new ArrayList<JavaModelBean>();
		for (JavaModelBean bean : getModel().getBeanList()) {
			if (bean.isExecutable()) {
				list.add(bean);
			}
		}
		return list;
	}

}
